package com.usian.search.service.impl;

import com.usian.common.util.JsonUtils;
import com.usian.model.article.dtos.ArticleDto;
import com.usian.model.search.dtos.UserSearchDto;
import com.usian.search.service.ApArticleSearchService;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @author Fay
 * @date 2022/7/21&18:48
 */
@Service
public class ApArticleSearchServiceImpl implements ApArticleSearchService {
    @Autowired
    private RestHighLevelClient restHighLevelClient;

    private String indexName = "app_info_article";
    /**
     * 向mango导入数据
     * @param articleDto
     */
    @Override
    public void createIndex(ArticleDto articleDto) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("layout",articleDto.getLayout());
        map.put("publishTime",articleDto.getPublishTime());
        map.put("images",articleDto.getImages());
        map.put("id",articleDto.getId());
        map.put("authorId",articleDto.getAuthorId());
        map.put("title",articleDto.getTitle());
        String articleJson = JsonUtils.toString(map);
        IndexRequest indexRequest = new IndexRequest(indexName).id(articleDto.getId().toString()).source(articleJson, XContentType.JSON);
        try {
            restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * es文章搜索引擎
     * @param userSearchDto
     * @return
     */
    @Override
    public List<ArticleDto> esArticleSearch(UserSearchDto userSearchDto) {
        //根据标题模糊查询
        //构建查询请求对象
        SearchRequest searchRequest =new SearchRequest("app_info_article");
        //创建查询构建器
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //根据标题模糊查询
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", userSearchDto.getSearchWords()).operator(Operator.AND);
        //布尔词条查询
        boolQueryBuilder.must(matchQueryBuilder);
        //对dto中的最小时间进行判断 如果不为空
        if (userSearchDto.getMinBehotTime()!=null){
            //进行过滤查询 只匹配发布时间大于最小时间的
            RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("publishTime").lte(userSearchDto.getMinBehotTime());
            boolQueryBuilder.filter(rangeQueryBuilder);
        }
        //进行查询
        sourceBuilder.query(boolQueryBuilder);
        //根据time排序 倒叙
        sourceBuilder.sort("publishTime", SortOrder.DESC);
        //分页查询
        sourceBuilder.from(userSearchDto.getFromIndex());
        sourceBuilder.size(userSearchDto.getPageSize());
        //去查询
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = null;
        try {
            //查询返回最后数据
            searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //对数据进行解析
        SearchHit[] hits = searchResponse.getHits().getHits();
        ArrayList<ArticleDto> articleDtoList = new ArrayList<>();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            //转换成java对象
            ArticleDto articleDto = JsonUtils.toBean(sourceAsString, ArticleDto.class);
            articleDtoList.add(articleDto);
        }
        return articleDtoList;
    }
}
